/**
 * SIP Response Reasons
 * DOC: http://www.iana.org/assignments/sip-parameters
 * @internal
 */
const REASON_PHRASE: { [code: number]: string } = {
  100: "Trying",
  180: "Ringing",
  181: "Call Is Being Forwarded",
  182: "Queued",
  183: "Session Progress",
  199: "Early Dialog Terminated", // draft-ietf-sipcore-199
  200: "OK",
  202: "Accepted", // RFC 3265
  204: "No Notification", // RFC 5839
  300: "Multiple Choices",
  301: "Moved Permanently",
  302: "Moved Temporarily",
  305: "Use Proxy",
  380: "Alternative Service",
  400: "Bad Request",
  401: "Unauthorized",
  402: "Payment Required",
  403: "Forbidden",
  404: "Not Found",
  405: "Method Not Allowed",
  406: "Not Acceptable",
  407: "Proxy Authentication Required",
  408: "Request Timeout",
  410: "Gone",
  412: "Conditional Request Failed", // RFC 3903
  413: "Request Entity Too Large",
  414: "Request-URI Too Long",
  415: "Unsupported Media Type",
  416: "Unsupported URI Scheme",
  417: "Unknown Resource-Priority", // RFC 4412
  420: "Bad Extension",
  421: "Extension Required",
  422: "Session Interval Too Small", // RFC 4028
  423: "Interval Too Brief",
  428: "Use Identity Header", // RFC 4474
  429: "Provide Referrer Identity", // RFC 3892
  430: "Flow Failed", // RFC 5626
  433: "Anonymity Disallowed", // RFC 5079
  436: "Bad Identity-Info", // RFC 4474
  437: "Unsupported Certificate", // RFC 4744
  438: "Invalid Identity Header", // RFC 4744
  439: "First Hop Lacks Outbound Support", // RFC 5626
  440: "Max-Breadth Exceeded", // RFC 5393
  469: "Bad Info Package", // draft-ietf-sipcore-info-events
  470: "Consent Needed", // RFC 5360
  478: "Unresolvable Destination", // Custom code copied from Kamailio.
  480: "Temporarily Unavailable",
  481: "Call/Transaction Does Not Exist",
  482: "Loop Detected",
  483: "Too Many Hops",
  484: "Address Incomplete",
  485: "Ambiguous",
  486: "Busy Here",
  487: "Request Terminated",
  488: "Not Acceptable Here",
  489: "Bad Event", // RFC 3265
  491: "Request Pending",
  493: "Undecipherable",
  494: "Security Agreement Required", // RFC 3329
  500: "Internal Server Error",
  501: "Not Implemented",
  502: "Bad Gateway",
  503: "Service Unavailable",
  504: "Server Time-out",
  505: "Version Not Supported",
  513: "Message Too Large",
  580: "Precondition Failure", // RFC 3312
  600: "Busy Everywhere",
  603: "Decline",
  604: "Does Not Exist Anywhere",
  606: "Not Acceptable"
};

/**
 * @param size -
 * @param base -
 * @internal
 */
export function createRandomToken(size: number, base = 32): string {
  let token = "";
  for (let i = 0; i < size; i++) {
    const r: number = Math.floor(Math.random() * base);
    token += r.toString(base);
  }
  return token;
}

/**
 * @internal
 */
export function getReasonPhrase(code: number): string {
  return REASON_PHRASE[code] || "";
}

/**
 * @internal
 */
export function newTag(): string {
  return createRandomToken(10);
}

/**
 * @param str -
 * @internal
 */
export function headerize(str: string): string {
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const exceptions: any = {
    "Call-Id": "Call-ID",
    Cseq: "CSeq",
    "Min-Se": "Min-SE",
    Rack: "RAck",
    Rseq: "RSeq",
    "Www-Authenticate": "WWW-Authenticate"
  };
  const name: Array<string> = str.toLowerCase().replace(/_/g, "-").split("-");
  const parts: number = name.length;
  let hname = "";

  for (let part = 0; part < parts; part++) {
    if (part !== 0) {
      hname += "-";
    }
    hname += name[part].charAt(0).toUpperCase() + name[part].substring(1);
  }
  if (exceptions[hname]) {
    hname = exceptions[hname];
  }
  return hname;
}

/**
 * @param str -
 * @internal
 */
export function utf8Length(str: string): number {
  return encodeURIComponent(str).replace(/%[A-F\d]{2}/g, "U").length;
}
